<template>
  <div class="chat">
    <div class="chat-map" id="chat-map">
      <!-- 左上角控制面板 -->
      <div class="map-controls">
        <!-- 图层切换下拉选择器 -->
        <div class="layer-control">
          <el-select v-model="selectedLayer" @change="switchLayer" placeholder="选择图层">
            <el-option label="标准图层" value="standard"></el-option>
            <el-option label="卫星图层" value="satellite"></el-option>
          </el-select>
        </div>

        <!-- 经纬度输入框 -->
        <div class="coordinate-input">
          <el-input v-model="coordinateInput" placeholder="格式: 经度,纬度" clearable
            @clear="handleCoordinateClear"></el-input>
          <el-button type="primary" size="small" @click="searchCoordinate">
            搜索
          </el-button>
        </div>
      </div>
    </div>

    <div class="chat-set">
      <el-scrollbar>
        <div>倾斜航线(五向交叉)</div>
        <div class="button-group">
          <el-button type="primary" @click="startDraw" :disabled="isDrawDisabled">
            绘制航线区域
          </el-button>
          <el-button type="danger" @click="deletePolygon" :disabled="!isDrawCompleted">
            删除
          </el-button>
        </div>

        <div class="area-info">
          <div>作业信息</div>
          <el-form :model="form1">
            <el-form-item label="区域总面积">
              <div>{{ area.toFixed(2) || 0 }} 平方公里</div>
            </el-form-item>
            <el-form-item label="单价(元/平方公里)">
              <el-input-number v-model="form1.unitPrice" :step="20" :min="0" />
            </el-form-item>
            <el-form-item label="费用预估(元)">
              <div>{{ (form1.unitPrice * (area.toFixed(6) || 0)).toFixed(0) }}</div>
            </el-form-item>
            <el-form-item label="飞行任务名称">
              <el-input v-model="form1.name" />
            </el-form-item>

            <div>
              航点数:{{ hds }} 航线数:{{ hxs }} 作业总耗时:{{ (zycd / form1.speed / 60).toFixed(0) }}分钟 照片数:{{ hds }} 作业总长度:{{
                (zycd / 1000).toFixed(2) }}公里
            </div>
            <div>
              航向间隔(m) <span style="color: #20a0ff;">{{ hxjg_pxjg[0] }}</span>
              旁向间隔(m) <span style="color: #008000;">{{ hxjg_pxjg[1] }}</span>

            </div>
            <el-tabs v-model="activeName" class="demo-tabs">
              <el-tab-pane label="基础设置" name="first"> <el-form-item label="选择机型">
                  <el-select v-model="form1.jixin" placeholder="请选择">
                    <el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value">
                    </el-option>
                  </el-select>
                </el-form-item>
                <el-form-item label="hg/gsd">
                  {{ form1.hg_gsd }}
                </el-form-item>
                <el-form-item label="飞行速度(m/s)">
                  <el-input-number v-model="form1.speed" :step="0.5" :min="0.5" :max="16" />
                </el-form-item>
                <el-form-item label="飞行高度(米)">
                  <el-input-number v-model="form1.hg" @change="setghgsd(0, $event)" :step="1" :min="2" :max="500" />
                </el-form-item>

                <el-form-item label="gsd(cm/pixel)">
                  <el-input v-model="form1.gsd" @change="setghgsd(1, $event)" />
                </el-form-item></el-tab-pane>
              <el-tab-pane label="相机设置" name="second">
                <el-form-item label="图像宽度(像素)">

                  <el-input-number v-model="form1.imgWidth" :step="1" @change="getFlyLine()" />
                </el-form-item>
                <el-form-item label="图像高度(像素)">
                  <el-input-number v-model="form1.imgHeight" :step="1" @change="getFlyLine()" />
                </el-form-item>


                相机角度 建议高层-60 低矮区-45
                <el-form-item :label="`相机角度: ${form1.xjjd}`">
                  <el-slider v-model="form1.xjjd" :min="-90" :max="0" :step="1"
                    :marks="{ '-90': '-90', '-60': '-60', '-45': '-45', '0': '0' }" />

                </el-form-item>

              </el-tab-pane>
              <el-tab-pane label="重叠设置" name="third">
                <el-form-item :label="`主航线角度: ${form1.zhxxzjd}`">
                  <el-slider v-model="form1.zhxxzjd" :min="0" :max="360" :step="1" show-input @change="getFlyLine()"
                    :marks="{ '0': '0', '90': '90', '180': '180', '270': '270' }" />

                </el-form-item>
                <el-form-item :label="`航向重叠率: ${form1.forwardOverlap}`">
                  <el-slider v-model="form1.forwardOverlap" :min="0.5" :max="0.99" :step="0.05" @change="getFlyLine()"
                    :marks="{ '0.7': '0.7', '0.75': '0.75', '0.8': '0.8' }" />

                </el-form-item>

                <el-form-item :label="`旁向重叠率: ${form1.sideOverlap}`">
                  <el-slider v-model="form1.sideOverlap" :min="0.5" :max="0.99" :step="0.05" @change="getFlyLine()"
                    :marks="{ '0.7': '0.7', '0.8': '0.8' }" />

                </el-form-item>
              </el-tab-pane>
              <el-tab-pane label="生成任务" name="first1">
                <el-button type="primary" :disabled="!isDrawCompleted" @click="getFlyLine">生成航线</el-button>


                <el-form-item label="五向交叉">
                  <el-radio-group v-model="form1.wxjc" @change="addFlyLine(mergeArrays(flyLinePoint[form1.wxjc]))">
                    <el-radio value="0" size="large">1</el-radio>
                    <el-radio value="1" size="large">2</el-radio>
                    <el-radio value="2" size="large">3</el-radio>
                    <el-radio value="3" size="large">4</el-radio>
                    <el-radio value="4" size="large">5</el-radio>
                  </el-radio-group>
                </el-form-item>
                <el-form-item label="单次飞行时间(分钟)">
                  <el-input-number v-model="form1.oneTime" :min="15" :step="1" />
                </el-form-item>
                <div>飞行次数:{{ flyCount }}</div>

                <el-button type="primary" :disabled="flyLinePoint.length == 0" @click="exportFlyLine">导出航线</el-button>

              </el-tab-pane>
            </el-tabs>


          </el-form>
        </div>
      </el-scrollbar>
    </div>










    <!-- 输出-------------------------------------------------------------------- -->
    <el-dialog v-model="dialogVisible" title="Tips" width="1200">
      <div>
        <h2 style="font-weight: bold; font-size: 20px; color: red;">遵守法律法规!注意飞行安全!</h2>
        导出说明:
        <div>无人机飞往航线起点的模式: {{ exportConfig.flyToWaylineMode.name }}</div>
        <div>任务完成后的动作: {{ exportConfig.finishAction.name }}</div>
        <div>遥控器信号丢失时的处理策略: {{ exportConfig.exitOnRCLost.name }}</div>
        <div>具体的信号丢失动作: {{ exportConfig.executeRCLostAction.name }}</div>
        <div>全局过渡速度: {{ form1.speed }}m/s</div>




        <el-tabs v-model="activetest" class="demo-tabs">

          <el-tab-pane label="template.kml" :name="0">
            <el-scrollbar>
              {{ template }}
            </el-scrollbar>
          </el-tab-pane>



          <el-tab-pane v-for="(item, index) in testwaylines" :key="index" :label="`测试航线安全${index + 1}-waylines.wpml`"
            :name="index + 1">
            <el-scrollbar>{{ item }}</el-scrollbar>
          </el-tab-pane>


          <el-tab-pane v-for="(item, index) in waylines" :key="index" :label="`飞行任务${index + 1}-waylines.wpml`"
            :name="index + 2">
            <el-scrollbar>{{ item }}</el-scrollbar>
          </el-tab-pane>

        </el-tabs>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogVisible = false">Cancel</el-button>

        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { saveAs } from 'file-saver';
import { ref, onMounted, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import icon from './circle.png'






//---------------------------------------------
let activetest = 0
let dialogVisible = ref(false)

// template.kml
let template = ''

// 测试waylines.wpml
let testwaylines = []

// 任务waylines.wpml 

let waylines = []

/*
<wpml:flyToWaylineMode>safely</wpml:flyToWaylineMode>：无人机飞往航线起点的模式，“safely” 表示 “安全模式”（可能指以避障、低风险方式飞行到航线起点）。
<wpml:finishAction>goHome</wpml:finishAction>：任务完成后的动作，“goHome” 表示 “自动返航”（飞回起飞点）。
<wpml:exitOnRCLost>executeLostAction</wpml:exitOnRCLost>：遥控器信号丢失时的处理策略，“executeLostAction” 表示 “执行预设的丢失信号动作”。
<wpml:executeRCLostAction>goBack</wpml:executeRCLostAction>：具体的信号丢失动作，“goBack” 表示 “返回”（可能返回上一个航点或起点）。
<wpml:globalTransitionalSpeed>2.5</wpml:globalTransitionalSpeed>：全局过渡速度，推测为无人机在航点间移动的速度（单位可能为米 / 秒）。
*/
const exportConfig = ref({
  flyToWaylineMode: {
    name: '安全模式',
    value: 'safely'
  },
  finishAction: {
    name: '自动返航',
    value: 'goHome'
  },
  exitOnRCLost: {
    name: '执行预设的丢失信号动作',
    value: 'executeLostAction'
  },
  executeRCLostAction: {
    name: '返回上一航点',
    value: 'goBack'
  }
})


// --------------------------------------------



// 拆分任务之后的任务
let taskflyLinePoint = ref([])
let testflyLinePoint = ref([])

// 航线点
let flyLinePoint = ref([])

let form1 = ref({
  oneTime: 60,
  speed: 12.0,
  unitPrice: 1000, // 价格
  jixin: null,      // 机型
  hg: 100,         //航高
  hg_gsd: 29.15451895043732, // gsd 不知道 一个比值
  gsd: 3.43,
  name: '', // 飞行任务名称
  imgWidth: 4000, // 图像宽度(像素)
  imgHeight: 3000, // 图像高度(像素)
  forwardOverlap: 0.8, // 航向重叠率
  sideOverlap: 0.7,     // 旁向重叠率70%
  zhxxzjd: 0,    // 主航线旋转角度
  xjjd: -60,      // 相机角度
  wxjc: '0',
})


let options1 = ref([
  {
    value: '2',
    label: 'Air3 s',
    hg_gsd: 29.15451895043732,
    imgWidth: 4032,
    imgHeight: 3023,
  }, {
    value: '1',
    label: 'mini 4 pro',
    hg_gsd: 29.15451895043732,
    imgWidth: 4032,
    imgHeight: 3023,
    droneEnumValue: 66

  }, {
    value: '-1',
    label: '其他',
    hg_gsd: 30,
    imgWidth: 4000,
    imgHeight: 3000,
  }])

//航线长度

// 主计算属性：整合所有逻辑计算总距离
const zycd = computed(() => {
  // 1. 展平三层数组为一维点数组
  const flatPoints = [];
  flyLinePoint.value.forEach(outerArray => {
    outerArray.forEach(middleArray => {
      flatPoints.push(...middleArray);
    });
  });

  // 2. 如果点数不足2个，返回0
  if (flatPoints.length < 2) return 0;

  // 3. 角度转弧度工具函数
  const toRadians = (degrees) => degrees * (Math.PI / 180);

  // 4. 两点距离计算函数
  const calculatePointDistance = (p1, p2) => {
    const earthRadius = 6371000; // 地球半径（米）

    const lat1 = toRadians(p1.lat);
    const lon1 = toRadians(p1.lng);
    const lat2 = toRadians(p2.lat);
    const lon2 = toRadians(p2.lng);

    const dLat = lat2 - lat1;
    const dLon = lon2 - lon1;

    // 哈维正弦公式
    const a = Math.sin(dLat / 2) ** 2 +
      Math.cos(lat1) * Math.cos(lat2) *
      Math.sin(dLon / 2) ** 2;

    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    return earthRadius * c;
  };

  // 5. 累加所有相邻点的距离
  let total = 0;
  for (let i = 0; i < flatPoints.length - 1; i++) {
    total += calculatePointDistance(flatPoints[i], flatPoints[i + 1]);
  }

  return total;
});
// 航点数
const hds = computed(() => {
  // 第一层遍历：外层数组
  return flyLinePoint.value.reduce((total, middleArray) => {
    // 第二层遍历：中层数组，累加每个中层数组包含的坐标点数量
    const middleTotal = middleArray.reduce((midTotal, pointArray) => {
      return midTotal + pointArray.length; // 第三层：坐标点数组的长度
    }, 0);
    return total + middleTotal;
  }, 0); // 初始值为0
});

// 航线数
const hxs = computed(() => {
  // 第一层遍历：外层数组
  return flyLinePoint.value.reduce((total, middleArray) => {
    // 第二层遍历：中层数组，累加每个中层数组包含的坐标点数量
    return total + middleArray.length; // 第三层：坐标点数组的长度

  }, 0); // 初始值为0
});

// 任务分段数
let flyCount = computed(() => {
  return Math.ceil(((zycd.value / form1.value.speed)) / (form1.value.oneTime * 60)) || 0
})

// 航向间隔_旁向间隔
const hxjg_pxjg = computed(() => {
  function calculateFiveWayIntervals() {
    let height = form1.value.hg
    let gsd = form1.value.gsd
    // 默认参数配置（五向交叉飞行常用参数）
    const defaults = {
      imgWidth: form1.value.imgWidth,      // 图像宽度(像素)
      imgHeight: form1.value.imgHeight,     // 图像高度(像素)
      forwardOverlap: form1.value.forwardOverlap, // 航向重叠率80%
      sideOverlap: form1.value.sideOverlap     // 旁向重叠率70%
    };

    // 合并参数
    const { imgWidth, imgHeight, forwardOverlap, sideOverlap } = { ...defaults };

    // 将GSD从厘米转换为米
    const gsdInMeter = gsd / 100;

    // 计算单张图像的地面覆盖尺寸
    const groundCoverageWidth = imgWidth * gsdInMeter;  // 地面宽度(米)
    const groundCoverageHeight = imgHeight * gsdInMeter; // 地面高度(米)

    // 计算间隔
    const courseInterval = groundCoverageHeight * (1 - forwardOverlap); // 航向间隔
    const sideInterval = groundCoverageWidth * (1 - sideOverlap);       // 旁向间隔

    // 返回保留两位小数的结果
    return {
      courseInterval: parseFloat(courseInterval.toFixed(2)),
      sideInterval: parseFloat(sideInterval.toFixed(2))
    };
  }
  let a = calculateFiveWayIntervals()
  return [a.courseInterval, a.sideInterval]
})

const changejixin = (value) => {
  const selectedItem = options1.value.find(item => item.value === value);
  form1.value.imgWidth = selectedItem.imgWidth
  form1.value.imgHeight = selectedItem.imgHeight

  setghgsd(0, form1.value.hg)
}
watch(
  () => form1.value.jixin,
  (newVal, oldVal) => {
    if (newVal) {
      changejixin(newVal)
    }

  },
  {
    immediate: true, // 立即执行一次回调（初始值时）
    deep: true // 深度监听（当监听对象时需要）
  }
)

const setghgsd = (type, val) => {
  if (type == 0) {
    form1.value.gsd = val / form1.value.hg_gsd
  } else {
    form1.value.hg = val * form1.value.hg_gsd

  }
  getFlyLine()


}

const activeName = ref('first')



let polyline = null

let labelsLayer = null

let pointsMarker = []

const removeFlyLine = () => {

  pointsMarker.forEach((item) => {
    labelsLayer.remove(item)
  })
  pointsMarker = []
  if (polyline) {
    map.remove(polyline); // 从地图上移除折线
    polyline = null
  }
}
const addFlyLine = (points) => {
  removeFlyLine()

  // 判断点
  /**
   * 统计前n个外层数组中所有坐标点的总数
   * @param {number} n - 要统计的前n个外层数组（从1开始）
   * @returns {number} 坐标点总数
   */
  const getCoordinateCount = (n) => {
    // 边界处理：如果n小于1或大于数组长度，返回0或实际存在的数量
    if (n < 1) return 0;
    const maxIndex = Math.min(n, flyLinePoint.value.length);

    // 截取前n个外层数组，然后累加所有点的数量
    return flyLinePoint.value
      .slice(0, maxIndex) // 取前n个外层数组
      .reduce((total, middleArray) => {
        // 累加当前外层数组中所有中层数组的点数量
        const middleTotal = middleArray.reduce((midTotal, pointArray) => {
          return midTotal + pointArray.length;
        }, 0);
        return total + middleTotal;
      }, 0);
  };

  let count = getCoordinateCount(form1.value.wxjc)
  let pointsList = []
  points.forEach((item, index) => {

    index += count
    index += 1
    pointsList.push(new AMap.LngLat(item.lng, item.lat))

    const labelMarker = new AMap.LabelMarker({
      name: index, //此属性非绘制文字内容，仅为标识使用
      position: [item.lng, item.lat], //基点位置
      zIndex: 0,
      icon: {
        type: "image", //图标类型，现阶段只支持 image 类型
        image: icon, //可访问的图片 URL
        size: [14, 14], //图片尺寸
        anchor: "center", //图片相对 position 的锚点，默认为 bottom-center
      },
      text: {
        content: index + '', //要展示的文字内容

        //文字样式

        style: {

          fontSize: 16, //字体大小
          fillColor: "#e68d00", //字体颜色

        },
      }
    })
    pointsMarker.push(labelMarker)
    labelsLayer.add(labelMarker);

  })



  polyline = new AMap.Polyline({
    path: pointsList,
    strokeWeight: 4, //线条宽度
    strokeColor: "#03df6d", //线条颜色
    lineJoin: "miter", //折线拐点连接处样式
  });
  map.add(polyline);


}




const getFlyLine = () => {
  if (!isDrawDisabled.value) {
    return
  }

  let routes1 = generateCrossRoutes(drawObj.getPath(), hxjg_pxjg.value[0], hxjg_pxjg.value[1], form1.value.zhxxzjd)

  let routes2 = JSON.parse(JSON.stringify(routes1))
  const reversedFirstLevel = routes2.reverse();
  routes2 = reversedFirstLevel.map(subArray => subArray.reverse());

  let routes3 = JSON.parse(JSON.stringify(routes1))

  let routes4 = generateCrossRoutes(drawObj.getPath(), hxjg_pxjg.value[0], hxjg_pxjg.value[1], form1.value.zhxxzjd + 90)

  let routes5 = JSON.parse(JSON.stringify(routes4))
  const reversedFirstLevel5 = routes5.reverse();
  routes5 = reversedFirstLevel5.map(subArray => subArray.reverse());

  // 正射标记
  routes3.forEach(item => {
    item.forEach(item2 => {
      item2.noRotate = true
    })
  })

  flyLinePoint.value = [routes1, routes2, routes3, routes4, routes5]

  console.log('得到航点数据', flyLinePoint.value)

  addFlyLine(mergeArrays(flyLinePoint.value[form1.value.wxjc]))

}


function mergeArrays(arrays) {
  // 如果传入的是一个数组（包含多个子数组），则直接使用它
  // 否则认为传入的是分散的数组参数，用arguments转换为数组
  const allArrays = Array.isArray(arrays) ? arrays : Array.from(arguments);

  return allArrays.reduce((result, current) => {
    // 确保当前元素是数组（容错处理）
    return result.concat(Array.isArray(current) ? current : []);
  }, []);
}
// ------------------------------------------------------------------导出逻辑-----------------------------------
const exportFlyLine = () => {
  // 获取时间 做任务分段
  function splitTaskData(taskData, splitCount) {
    // 深拷贝原始数据避免修改源数据
    const originalData = JSON.parse(JSON.stringify(taskData));

    // 边界情况处理
    if (splitCount <= 1) {
      return [originalData];
    }

    // 收集所有航点信息，同时记录其所属的子任务和航线
    const allWaypoints = [];
    originalData.forEach((subTask, subTaskIndex) => {
      subTask.forEach((route, routeIndex) => {
        route.forEach((waypoint, waypointIndex) => {
          allWaypoints.push({
            waypoint,
            subTaskIndex,
            routeIndex,
            waypointIndex
          });
        });
      });
    });

    const totalWaypoints = allWaypoints.length;
    // 计算最小航点数和需要分配额外航点的任务数量
    const baseWaypoints = Math.floor(totalWaypoints / splitCount);
    const extraWaypoints = totalWaypoints % splitCount;

    // 为每个任务设定目标航点数，前extraWaypoints个任务多分配1个
    const targetWaypoints = [];
    for (let i = 0; i < splitCount; i++) {
      targetWaypoints[i] = baseWaypoints + (i < extraWaypoints ? 1 : 0);
    }

    // 初始化结果数组
    const result = Array.from({ length: splitCount }, () => []);
    // 跟踪每个任务已分配的航点数
    const assignedCounts = new Array(splitCount).fill(0);
    // 当前正在处理的任务索引
    let currentTaskIndex = 0;

    // 遍历所有子任务和航线
    originalData.forEach((subTask, subTaskIndex) => {
      subTask.forEach((route, routeIndex) => {
        const routeWaypoints = [...route];

        // 如果航线航点不足4个，不拆分，整体分配
        if (routeWaypoints.length < 4) {
          // 找到可以容纳这条航线的任务
          let targetTaskIndex = currentTaskIndex;
          while (targetTaskIndex < splitCount) {
            const remainingCapacity = targetWaypoints[targetTaskIndex] - assignedCounts[targetTaskIndex];
            if (remainingCapacity >= routeWaypoints.length) {
              break;
            }
            targetTaskIndex++;
          }

          // 如果所有任务都装不下，放到最后一个任务
          if (targetTaskIndex >= splitCount) {
            targetTaskIndex = splitCount - 1;
          }

          // 添加到目标任务
          if (!result[targetTaskIndex][subTaskIndex]) {
            result[targetTaskIndex][subTaskIndex] = [];
          }
          result[targetTaskIndex][subTaskIndex].push(routeWaypoints);
          assignedCounts[targetTaskIndex] += routeWaypoints.length;

          // 更新当前任务索引
          currentTaskIndex = targetTaskIndex;
        } else {
          // 航点足够多，可以拆分
          let remainingWaypoints = [...routeWaypoints];

          while (remainingWaypoints.length >= 2) {
            // 计算当前任务还能容纳多少航点
            const remainingCapacity = targetWaypoints[currentTaskIndex] - assignedCounts[currentTaskIndex];

            // 如果当前任务已满，切换到下一个
            if (remainingCapacity <= 0 && currentTaskIndex < splitCount - 1) {
              currentTaskIndex++;
              continue;
            }

            // 确定本次要分配的航点数（至少2个）
            let takeCount = Math.min(remainingCapacity, remainingWaypoints.length);
            takeCount = Math.max(2, takeCount);

            // 如果取走后剩余不足2个，就一起取走
            if (remainingWaypoints.length - takeCount < 2) {
              takeCount = remainingWaypoints.length;
            }

            // 分配航点
            const assigned = remainingWaypoints.slice(0, takeCount);
            remainingWaypoints = remainingWaypoints.slice(takeCount);

            // 添加到当前任务
            if (!result[currentTaskIndex][subTaskIndex]) {
              result[currentTaskIndex][subTaskIndex] = [];
            }
            result[currentTaskIndex][subTaskIndex].push(assigned);
            assignedCounts[currentTaskIndex] += assigned.length;

            // 如果当前任务已满，切换到下一个任务
            if (assignedCounts[currentTaskIndex] >= targetWaypoints[currentTaskIndex] &&
              currentTaskIndex < splitCount - 1) {
              currentTaskIndex++;
            }
          }
        }
      });
    });

    // 清理空的子任务数组和空任务
    return result.map(task =>
      task.filter(subTask => subTask && subTask.length > 0)
    ).filter(task => task.length > 0);
  }

  //测试线路 
  let a =  JSON.parse(JSON.stringify(flyLinePoint.value[0])) 
  let b =   JSON.parse(JSON.stringify(flyLinePoint.value[flyLinePoint.value.length - 1]))  

  testflyLinePoint.value = [[a,b]]

  console.log('1111111111:', testflyLinePoint.value)



  // 拆分
  taskflyLinePoint.value = splitTaskData(flyLinePoint.value, flyCount.value)

  console.log('拆分任务:', taskflyLinePoint.value)

  // template

  template = `<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.2">
  <Document>
    <wpml:author>author</wpml:author>
    <wpml:createTime>1758342001854</wpml:createTime>
    <wpml:updateTime>1758342001854</wpml:updateTime>
    <wpml:missionConfig>
      <wpml:flyToWaylineMode>${exportConfig.value.flyToWaylineMode.value}</wpml:flyToWaylineMode>
      <wpml:finishAction>${exportConfig.value.finishAction.value}</wpml:finishAction>
      <wpml:exitOnRCLost>${exportConfig.value.exitOnRCLost.value}</wpml:exitOnRCLost>
      <wpml:executeRCLostAction>${exportConfig.value.executeRCLostAction.value}</wpml:executeRCLostAction>
      <wpml:globalTransitionalSpeed>${form1.value.speed}</wpml:globalTransitionalSpeed>
      <wpml:droneInfo>
        <wpml:droneEnumValue>68</wpml:droneEnumValue>
        <wpml:droneSubEnumValue>0</wpml:droneSubEnumValue>
      </wpml:droneInfo>
    </wpml:missionConfig>
  </Document>
</kml>
`


  testwaylines = []
  waylines = []


  testflyLinePoint.value.forEach(task=>{
      let testPlacemark = ``

    let pointIndex = 0

    task.forEach(task2 => {

      // 添加控制点 
      task2 = addControlPointFun(task2)

      task2.forEach(line => {
        line.forEach((point, index) => {

          let wgs = gcj02towgs84(point.lat, point.lng)

          point.lat = wgs.slat
          point.lng = wgs.slng


          // 测试
          testPlacemark += `
          <Placemark>
                <Point>
                    <coordinates>${point.lng},${point.lat}</coordinates>
                </Point>
                <wpml:index>${pointIndex}</wpml:index>
                <wpml:executeHeight>${form1.value.hg}</wpml:executeHeight>
                <wpml:waypointSpeed>${form1.value.speed}</wpml:waypointSpeed>
                <wpml:waypointHeadingParam>
                    <wpml:waypointHeadingMode>followWayline</wpml:waypointHeadingMode>
                    <wpml:waypointHeadingAngle>0</wpml:waypointHeadingAngle>
                    <wpml:waypointHeadingPathMode>followBadArc</wpml:waypointHeadingPathMode>
                </wpml:waypointHeadingParam>
                <wpml:waypointTurnParam>
                    <wpml:waypointTurnMode>toPointAndStopWithContinuityCurvature</wpml:waypointTurnMode>
                    <wpml:waypointTurnDampingDist>0</wpml:waypointTurnDampingDist>
                </wpml:waypointTurnParam>
                <wpml:useStraightLine>0</wpml:useStraightLine>
                <wpml:actionGroup>
                    <wpml:actionGroupId>${pointIndex}</wpml:actionGroupId>
                    <wpml:actionGroupStartIndex>${pointIndex}</wpml:actionGroupStartIndex>
                    <wpml:actionGroupEndIndex>${pointIndex}</wpml:actionGroupEndIndex>
                    <wpml:actionGroupMode>sequence</wpml:actionGroupMode>
                    <wpml:actionTrigger>
                        <wpml:actionTriggerType>reachPoint</wpml:actionTriggerType>
                    </wpml:actionTrigger>
                    <wpml:action>
                        <wpml:actionId>0</wpml:actionId>
                        <wpml:actionActuatorFunc>gimbalRotate</wpml:actionActuatorFunc>
                        <wpml:actionActuatorFuncParam>
                            <wpml:gimbalHeadingYawBase>aircraft</wpml:gimbalHeadingYawBase>
                            <wpml:gimbalRotateMode>absoluteAngle</wpml:gimbalRotateMode>
                            <wpml:gimbalPitchRotateEnable>1</wpml:gimbalPitchRotateEnable>
                            <wpml:gimbalPitchRotateAngle>0</wpml:gimbalPitchRotateAngle>
                            <wpml:gimbalRollRotateEnable>0</wpml:gimbalRollRotateEnable>
                            <wpml:gimbalRollRotateAngle>0</wpml:gimbalRollRotateAngle>
                            <wpml:gimbalYawRotateEnable>0</wpml:gimbalYawRotateEnable>
                            <wpml:gimbalYawRotateAngle>0</wpml:gimbalYawRotateAngle>
                            <wpml:gimbalRotateTimeEnable>0</wpml:gimbalRotateTimeEnable>
                            <wpml:gimbalRotateTime>0</wpml:gimbalRotateTime>
                            <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
                        </wpml:actionActuatorFuncParam>
                    </wpml:action>
                </wpml:actionGroup>
            </Placemark>
            `

       



          pointIndex += 1
        })
      })




    })






    //testwaylines

    let testFolder = `<Folder>
            <wpml:templateId>0</wpml:templateId>
            <wpml:waylineId>0</wpml:waylineId>
            <wpml:autoFlightSpeed>${form1.value.speed}</wpml:autoFlightSpeed>
            <wpml:executeHeightMode>relativeToStartPoint</wpml:executeHeightMode>
            <wpml:payloadParam>
                <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
                <wpml:imageFormat>wide</wpml:imageFormat>
            </wpml:payloadParam>
          ${testPlacemark}
            </Folder>
            `
    let testwaylinesXml = `<?xml version="1.0" encoding="UTF-8"?>

<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.2">
  <Document>
    <wpml:missionConfig>
      <wpml:flyToWaylineMode>${exportConfig.value.flyToWaylineMode.value}</wpml:flyToWaylineMode>
      <wpml:finishAction>${exportConfig.value.finishAction.value}</wpml:finishAction>
      <wpml:exitOnRCLost>${exportConfig.value.exitOnRCLost.value}</wpml:exitOnRCLost>
      <wpml:executeRCLostAction>${exportConfig.value.executeRCLostAction.value}</wpml:executeRCLostAction>
      <wpml:globalTransitionalSpeed>${form1.value.speed}</wpml:globalTransitionalSpeed>
      <wpml:droneInfo>
        <wpml:droneEnumValue>68</wpml:droneEnumValue>
        <wpml:droneSubEnumValue>0</wpml:droneSubEnumValue>
      </wpml:droneInfo>
       <wpml:payloadInfo>
                <wpml:payloadEnumValue></wpml:payloadEnumValue>
                <wpml:payloadSubEnumValue>0</wpml:payloadSubEnumValue>
                <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
            </wpml:payloadInfo>
    </wpml:missionConfig>
  ${testFolder}
     </Document>
</kml>`

    testwaylines.push(testwaylinesXml)


  })



  taskflyLinePoint.value.forEach(task => {

    let Placemark = ``

    let pointIndex = 0

    task.forEach(task2 => {

      // 添加控制点 
      task2 = addControlPointFun(task2)

      task2.forEach(line => {
        line.forEach((point, index) => {

          let wgs = gcj02towgs84(point.lat, point.lng)

          point.lat = wgs.slat
          point.lng = wgs.slng


        // 作业

          if (point.isControl) {
            let Rotate = line[index + 1]?.noRotate ? '-90' : form1.value.xjjd
            // 控制点
            Placemark += `
 <Placemark>
                <Point>
                    <coordinates>${point.lng},${point.lat}</coordinates>
                </Point>
                <wpml:index>${pointIndex}</wpml:index>
                <wpml:executeHeight>${form1.value.hg}</wpml:executeHeight>
                <wpml:waypointSpeed>${form1.value.speed}</wpml:waypointSpeed>
                <wpml:waypointHeadingParam>
                    <wpml:waypointHeadingMode>followWayline</wpml:waypointHeadingMode>
                    <wpml:waypointHeadingAngle>0</wpml:waypointHeadingAngle>
                    <wpml:waypointHeadingPathMode>followBadArc</wpml:waypointHeadingPathMode>
                </wpml:waypointHeadingParam>
                <wpml:waypointTurnParam>
                    <wpml:waypointTurnMode>toPointAndStopWithContinuityCurvature</wpml:waypointTurnMode>
                    <wpml:waypointTurnDampingDist>0</wpml:waypointTurnDampingDist>
                </wpml:waypointTurnParam>
                <wpml:useStraightLine>0</wpml:useStraightLine>
                <wpml:actionGroup>
                    <wpml:actionGroupId>${pointIndex}</wpml:actionGroupId>
                    <wpml:actionGroupStartIndex>${pointIndex}</wpml:actionGroupStartIndex>
                    <wpml:actionGroupEndIndex>${pointIndex}</wpml:actionGroupEndIndex>
                    <wpml:actionGroupMode>sequence</wpml:actionGroupMode>
                    <wpml:actionTrigger>
                        <wpml:actionTriggerType>reachPoint</wpml:actionTriggerType>
                        <wpml:actionTriggerParam>${Rotate}</wpml:actionTriggerParam>
                    </wpml:actionTrigger>
                    <wpml:action>
                        <wpml:actionId>0</wpml:actionId>
                        <wpml:actionActuatorFunc>hover</wpml:actionActuatorFunc>
                        <wpml:actionActuatorFuncParam>
                            <wpml:hoverTime>0.5</wpml:hoverTime>
                        </wpml:actionActuatorFuncParam>
                    </wpml:action>
                    <wpml:action>
                        <wpml:actionId>1</wpml:actionId>
                        <wpml:actionActuatorFunc>gimbalRotate</wpml:actionActuatorFunc>
                        <wpml:actionActuatorFuncParam>
                            <wpml:gimbalHeadingYawBase>aircraft</wpml:gimbalHeadingYawBase>
                            <wpml:gimbalRotateMode>absoluteAngle</wpml:gimbalRotateMode>
                            <wpml:gimbalPitchRotateEnable>1</wpml:gimbalPitchRotateEnable>
                            <wpml:gimbalPitchRotateAngle>${Rotate}</wpml:gimbalPitchRotateAngle>
                            <wpml:gimbalRollRotateEnable>0</wpml:gimbalRollRotateEnable>
                            <wpml:gimbalRollRotateAngle>0</wpml:gimbalRollRotateAngle>
                            <wpml:gimbalYawRotateEnable>0</wpml:gimbalYawRotateEnable>
                            <wpml:gimbalYawRotateAngle>0</wpml:gimbalYawRotateAngle>
                            <wpml:gimbalRotateTimeEnable>0</wpml:gimbalRotateTimeEnable>
                            <wpml:gimbalRotateTime>0</wpml:gimbalRotateTime>
                            <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
                        </wpml:actionActuatorFuncParam>
                    </wpml:action>
                </wpml:actionGroup>
            </Placemark>
 `
          } else {
            // 拍照
            Placemark += `<Placemark>	
                <Point>
                    <coordinates>${point.lng},${point.lat}</coordinates>
                </Point>
                <wpml:index>${pointIndex}</wpml:index>
                <wpml:executeHeight>${form1.value.hg}</wpml:executeHeight>
                <wpml:waypointSpeed>${form1.value.speed}</wpml:waypointSpeed>
                <wpml:waypointHeadingParam>
                    <wpml:waypointHeadingMode>followWayline</wpml:waypointHeadingMode>
                    <wpml:waypointHeadingAngle>0</wpml:waypointHeadingAngle>
                    <wpml:waypointHeadingPathMode>followBadArc</wpml:waypointHeadingPathMode>
                </wpml:waypointHeadingParam>
                <wpml:waypointTurnParam>
                    <wpml:waypointTurnMode>toPointAndStopWithContinuityCurvature</wpml:waypointTurnMode>
                    <wpml:waypointTurnDampingDist>0</wpml:waypointTurnDampingDist>
                </wpml:waypointTurnParam>
                <wpml:useStraightLine>0</wpml:useStraightLine>
                <wpml:actionGroup>
                    <wpml:actionGroupId>${pointIndex}</wpml:actionGroupId>
                    <wpml:actionGroupStartIndex>${pointIndex}</wpml:actionGroupStartIndex>
                    <wpml:actionGroupEndIndex>${pointIndex}</wpml:actionGroupEndIndex>
                    <wpml:actionGroupMode>sequence</wpml:actionGroupMode>
                    <wpml:actionTrigger>
                        <wpml:actionTriggerType>reachPoint</wpml:actionTriggerType>
                        <wpml:actionTriggerParam>${point.noRotate ? '-90' : form1.value.xjjd}</wpml:actionTriggerParam>
                    </wpml:actionTrigger>
                    <wpml:action>
                        <wpml:actionId>0</wpml:actionId>
                        <wpml:actionActuatorFunc>takePhoto</wpml:actionActuatorFunc>
                        <wpml:actionActuatorFuncParam>
                            <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
                            <wpml:fileSuffix>yuzhucg</wpml:fileSuffix>
                        </wpml:actionActuatorFuncParam>
                    </wpml:action>
                    <wpml:action>
                        <wpml:actionId>1</wpml:actionId>
                        <wpml:actionActuatorFunc>gimbalRotate</wpml:actionActuatorFunc>
                        <wpml:actionActuatorFuncParam>
                            <wpml:gimbalHeadingYawBase>aircraft</wpml:gimbalHeadingYawBase>
                            <wpml:gimbalRotateMode>absoluteAngle</wpml:gimbalRotateMode>
                            <wpml:gimbalPitchRotateEnable>1</wpml:gimbalPitchRotateEnable>
                            <wpml:gimbalPitchRotateAngle>${point.noRotate ? '-90' : form1.value.xjjd}</wpml:gimbalPitchRotateAngle>
                            <wpml:gimbalRollRotateEnable>0</wpml:gimbalRollRotateEnable>
                            <wpml:gimbalRollRotateAngle>0</wpml:gimbalRollRotateAngle>
                            <wpml:gimbalYawRotateEnable>0</wpml:gimbalYawRotateEnable>
                            <wpml:gimbalYawRotateAngle>0</wpml:gimbalYawRotateAngle>
                            <wpml:gimbalRotateTimeEnable>0</wpml:gimbalRotateTimeEnable>
                            <wpml:gimbalRotateTime>0</wpml:gimbalRotateTime>
                            <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
                        </wpml:actionActuatorFuncParam>
                    </wpml:action>
                </wpml:actionGroup>
            </Placemark>
      `


          }




          pointIndex += 1
        })
      })




    })






 
    // waylines

    let Folder = `<Folder>
            <wpml:templateId>0</wpml:templateId>
            <wpml:waylineId>0</wpml:waylineId>
            <wpml:autoFlightSpeed>${form1.value.speed}</wpml:autoFlightSpeed>
            <wpml:executeHeightMode>relativeToStartPoint</wpml:executeHeightMode>
            <wpml:payloadParam>
                <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
                <wpml:imageFormat>wide</wpml:imageFormat>
            </wpml:payloadParam>
            ${Placemark}
            </Folder>
            `
    let waylinesXml = `<?xml version="1.0" encoding="UTF-8"?>

<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.2">
  <Document>
    <wpml:missionConfig>
      <wpml:flyToWaylineMode>${exportConfig.value.flyToWaylineMode.value}</wpml:flyToWaylineMode>
      <wpml:finishAction>${exportConfig.value.finishAction.value}</wpml:finishAction>
      <wpml:exitOnRCLost>${exportConfig.value.exitOnRCLost.value}</wpml:exitOnRCLost>
      <wpml:executeRCLostAction>${exportConfig.value.executeRCLostAction.value}</wpml:executeRCLostAction>
      <wpml:globalTransitionalSpeed>${form1.value.speed}</wpml:globalTransitionalSpeed>
      <wpml:droneInfo>
        <wpml:droneEnumValue>68</wpml:droneEnumValue>
        <wpml:droneSubEnumValue>0</wpml:droneSubEnumValue>
      </wpml:droneInfo>
       <wpml:payloadInfo>
                <wpml:payloadEnumValue></wpml:payloadEnumValue>
                <wpml:payloadSubEnumValue>0</wpml:payloadSubEnumValue>
                <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
            </wpml:payloadInfo>
    </wpml:missionConfig>
  ${Folder}
     </Document>
</kml>`

    waylines.push(waylinesXml)



  })


// console.log('template',template)
// console.log('testwaylines',testwaylines)
// console.log('waylines',waylines)


const templatexml = template;
const blob = new Blob([templatexml], { type: 'text/plain;charset=utf-8' });
saveAs(blob, 'template.kml');


testwaylines.forEach((item,index)=>{
const blobtestwaylinesxml = new Blob([item], { type: 'text/plain;charset=utf-8' });
saveAs(blobtestwaylinesxml, `${index+1}-testwaylines.wpml`);
})


waylines.forEach((item,index)=>{
const blobwaylinesxml = new Blob([item], { type: 'text/plain;charset=utf-8' });
saveAs(blobwaylinesxml, `${index+1}-waylines.wpml`);
})






  dialogVisible.value = true


}


// 添加控制点方法

const addControlPointFun = (routes) => {

  return addControlPoint(routes, 0.1)


  /**
   * 在第一条航线的开头添加一个控制点
   * @param {Array} routes - 航线数组
   * @param {number} distance - 距离第一个点的距离(米)
   * @returns {Array} 添加了控制点的新航线数组
   */
  function addControlPoint(routes, distance = 0.1) {
    // 检查是否有航线数据
    if (!routes || routes.length === 0) {
      throw new Error("No route data available");
    }

    // 复制原始数据，避免修改原数组
    const newRoutes = JSON.parse(JSON.stringify(routes));
    const firstRoute = newRoutes[0];

    // 检查第一条航线是否有足够的点来确定方向
    if (firstRoute.length < 2) {
      throw new Error("First route needs at least 2 points to determine direction");
    }

    // 获取第一条航线的前两个点，用于确定方向
    const firstPoint = firstRoute[0];
    const secondPoint = firstRoute[1];

    // 计算两点之间的方位角(度)
    const bearing = calculateBearing(
      firstPoint.lat, firstPoint.lng,
      secondPoint.lat, secondPoint.lng
    );

    // 控制点应该在相反方向，所以加上180度
    const controlPointBearing = (bearing + 180) % 360;

    // 计算控制点坐标
    const controlPoint = calculateDestinationPoint(
      firstPoint.lat, firstPoint.lng,
      controlPointBearing,
      distance
    );

    // 添加标识字段
    controlPoint.noRotate = true;
    controlPoint.isControl = true;

    // 在第一条航线的开头插入控制点
    firstRoute.unshift(controlPoint);

    return newRoutes;
  }

  /**
   * 计算两点之间的方位角
   * @param {number} startLat - 起点纬度
   * @param {number} startLng - 起点经度
   * @param {number} endLat - 终点纬度
   * @param {number} endLng - 终点经度
   * @returns {number} 方位角(度)
   */
  function calculateBearing(startLat, startLng, endLat, endLng) {
    // 将度转换为弧度
    const startLatRadians = degreesToRadians(startLat);
    const endLatRadians = degreesToRadians(endLat);
    const longitudeDifference = degreesToRadians(endLng - startLng);

    // 计算方位角
    const y = Math.sin(longitudeDifference) * Math.cos(endLatRadians);
    const x = Math.cos(startLatRadians) * Math.sin(endLatRadians) -
      Math.sin(startLatRadians) * Math.cos(endLatRadians) * Math.cos(longitudeDifference);
    const angle = Math.atan2(y, x);

    // 将弧度转换为度，并调整为0-360度
    return (radiansToDegrees(angle) + 360) % 360;
  }

  /**
   * 根据起点、方位角和距离计算终点坐标
   * @param {number} lat - 起点纬度
   * @param {number} lng - 起点经度
   * @param {number} bearing - 方位角(度)
   * @param {number} distance - 距离(米)
   * @returns {Object} 终点坐标 {lat, lng}
   */
  function calculateDestinationPoint(lat, lng, bearing, distance) {
    const earthRadius = 6371000; // 地球半径(米)
    const startLatRadians = degreesToRadians(lat);
    const startLngRadians = degreesToRadians(lng);
    const bearingRadians = degreesToRadians(bearing);
    const distanceOverRadius = distance / earthRadius;

    // 计算终点纬度
    const endLatRadians = Math.asin(
      Math.sin(startLatRadians) * Math.cos(distanceOverRadius) +
      Math.cos(startLatRadians) * Math.sin(distanceOverRadius) * Math.cos(bearingRadians)
    );

    // 计算终点经度
    const endLngRadians = startLngRadians + Math.atan2(
      Math.sin(bearingRadians) * Math.sin(distanceOverRadius) * Math.cos(startLatRadians),
      Math.cos(distanceOverRadius) - Math.sin(startLatRadians) * Math.sin(endLatRadians)
    );

    // 将弧度转换为度，并返回结果
    return {
      lat: radiansToDegrees(endLatRadians),
      lng: radiansToDegrees(endLngRadians)
    };
  }

  /**
   * 将角度转换为弧度
   * @param {number} degrees - 角度
   * @returns {number} 弧度
   */
  function degreesToRadians(degrees) {
    return degrees * (Math.PI / 180);
  }

  /**
   * 将弧度转换为角度
   * @param {number} radians - 弧度
   * @returns {number} 角度
   */
  function radiansToDegrees(radians) {
    return radians * (180 / Math.PI);
  }




}



// ---------------------------------------------------------------------绘制航线--------------------------------------------------------------------------

/**
 * 高精度航线规划器（严格保证航向间隔和旁向间隔）
 * @param {Array} polygon 多边形经纬度点数组，格式: [{lng, lat}, ...]
 * @param {number} courseInterval 航向间隔(米) - 同航线点与点之间的距离
 * @param {number} sideInterval 旁向间隔(米) - 相邻平行航线之间的距离
 * @param {number} mainAngle 主航线旋转角度(0-360度)
 * @param {number} minPointDistance 点之间的最小距离(米)，默认与航向间隔相同
 * @returns {Object} 航线数组，每条航线为点数组 [[{lng, lat}, ...], ...]
 */
function generateCrossRoutes(polygon, courseInterval, sideInterval, mainAngle, minPointDistance = courseInterval) {

  if (courseInterval == 0 || sideInterval == 0) {
    return
  }
  mainAngle += 90
  // 常量定义
  const EARTH_RADIUS = 6371000; // 地球半径（米）
  const EPSILON = 1e-12; // 提高浮点数比较精度
  const DISTANCE_TOLERANCE = 0.1; // 距离误差容忍度（米）

  // 辅助函数：角度转弧度
  const toRadians = (degrees) => degrees * Math.PI / 180;

  // 辅助函数：弧度转角度
  const toDegrees = (radians) => radians * 180 / Math.PI;

  // 辅助函数：计算两点间距离（米）- 使用更精确的算法
  const calculateDistance = (point1, point2) => {
    const lat1Rad = toRadians(point1.lat);
    const lon1Rad = toRadians(point1.lng);
    const lat2Rad = toRadians(point2.lat);
    const lon2Rad = toRadians(point2.lng);

    const deltaLat = lat2Rad - lat1Rad;
    const deltaLon = lon2Rad - lon1Rad;

    // 使用Haversine公式的更精确实现
    const a = Math.sin(deltaLat / 2) ** 2 +
      Math.cos(lat1Rad) * Math.cos(lat2Rad) *
      Math.sin(deltaLon / 2) ** 2;
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    return EARTH_RADIUS * c;
  };

  // 辅助函数：根据起点、距离、角度计算终点 - 优化精度
  const destinationPoint = (point, distance, angle) => {
    const angularDistance = distance / EARTH_RADIUS; // 角距离（弧度）
    const angleRad = toRadians(angle);

    const latRad = toRadians(point.lat);
    const lonRad = toRadians(point.lng);

    // 更精确的球面计算
    const sinLat = Math.sin(latRad);
    const cosLat = Math.cos(latRad);
    const sinAngular = Math.sin(angularDistance);
    const cosAngular = Math.cos(angularDistance);
    const sinAngle = Math.sin(angleRad);
    const cosAngle = Math.cos(angleRad);

    const newLatRad = Math.asin(
      sinLat * cosAngular +
      cosLat * sinAngular * cosAngle
    );

    let newLonRad = lonRad + Math.atan2(
      sinAngle * sinAngular * cosLat,
      cosAngular - sinLat * Math.sin(newLatRad)
    );

    // 精确归一化经度到[-180, 180]
    newLonRad = ((newLonRad + 3 * Math.PI) % (2 * Math.PI) - Math.PI);

    return {
      lng: toDegrees(newLonRad),
      lat: toDegrees(newLatRad)
    };
  };

  // 优化的球面线性插值（确保点间距精确）
  const sphericalInterpolate = (start, end, targetInterval) => {
    const points = [start];
    const totalDistance = calculateDistance(start, end);

    // 如果总距离小于目标间隔，直接返回两点
    if (totalDistance < targetInterval - DISTANCE_TOLERANCE) {
      return [start, end];
    }

    let current = start;
    let remainingDistance = totalDistance;

    // 循环生成中间点，确保每个点都精确符合间隔要求
    while (remainingDistance > targetInterval + DISTANCE_TOLERANCE) {
      // 计算理论上下一个点
      let nextPoint = moveAlongBearing(current, end, targetInterval);

      // 检查实际距离并微调
      const actualDistance = calculateDistance(current, nextPoint);
      const distanceError = targetInterval - actualDistance;

      // 如果误差超过容忍度，进行修正
      if (Math.abs(distanceError) > DISTANCE_TOLERANCE) {
        // 计算修正角度，略微调整方向以补偿误差
        const bearing = calculateBearing(current, end);
        const adjustedBearing = distanceError > 0 ? bearing + 0.001 : bearing - 0.001;
        nextPoint = destinationPoint(current, targetInterval, adjustedBearing);
      }

      points.push(nextPoint);
      current = nextPoint;
      remainingDistance = calculateDistance(current, end);
    }

    // 添加终点，确保最后一段距离不超过目标间隔
    if (remainingDistance > DISTANCE_TOLERANCE) {
      points.push(end);
    } else {
      // 如果最后一段距离太小，替换为终点
      points[points.length - 1] = end;
    }

    return points;
  };

  // 辅助函数：计算两点间的方位角
  const calculateBearing = (start, end) => {
    const lat1Rad = toRadians(start.lat);
    const lat2Rad = toRadians(end.lat);
    const deltaLng = toRadians(end.lng - start.lng);

    const y = Math.sin(deltaLng) * Math.cos(lat2Rad);
    const x = Math.cos(lat1Rad) * Math.sin(lat2Rad) -
      Math.sin(lat1Rad) * Math.cos(lat2Rad) * Math.cos(deltaLng);

    let bearing = toDegrees(Math.atan2(y, x));
    // 归一化到0-360度
    return (bearing + 360) % 360;
  };

  // 辅助函数：沿两点方向移动指定距离（优化版）
  const moveAlongBearing = (start, end, distance) => {
    // 计算精确的方位角
    const bearing = calculateBearing(start, end);
    // 沿此方位角移动指定距离
    return destinationPoint(start, distance, bearing);
  };

  // 点在多边形内检测（射线法）
  const isPointInPolygon = (point, polygon) => {
    let inside = false;
    for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
      const xi = polygon[i].lng, yi = polygon[i].lat;
      const xj = polygon[j].lng, yj = polygon[j].lat;

      if (isPointOnSegment(point, { lng: xi, lat: yi }, { lng: xj, lat: yj })) {
        return true;
      }

      const intersect = ((yi > point.lat) !== (yj > point.lat)) &&
        (point.lng < (xj - xi) * (point.lat - yi) / (yj - yi + EPSILON) + xi);
      if (intersect) inside = !inside;
    }
    return inside;
  };

  // 点在线段上检测
  const isPointOnSegment = (point, a, b) => {
    if (Math.min(a.lng, b.lng) - EPSILON > point.lng || point.lng > Math.max(a.lng, b.lng) + EPSILON)
      return false;
    if (Math.min(a.lat, b.lat) - EPSILON > point.lat || point.lat > Math.max(a.lat, b.lat) + EPSILON)
      return false;

    const cross = (point.lng - a.lng) * (b.lat - a.lat) - (point.lat - a.lat) * (b.lng - a.lng);
    return Math.abs(cross) <= EPSILON;
  };

  // 线段与多边形交点计算
  const getIntersectionPoints = (start, end, polygon) => {
    const intersections = [];

    for (let i = 0; i < polygon.length; i++) {
      const a = polygon[i];
      const b = polygon[(i + 1) % polygon.length];
      const intersect = lineSegmentIntersection(start, end, a, b);

      if (intersect) {
        // 去重
        let isDuplicate = false;
        for (const p of intersections) {
          if (Math.abs(p.lng - intersect.lng) < EPSILON &&
            Math.abs(p.lat - intersect.lat) < EPSILON) {
            isDuplicate = true;
            break;
          }
        }
        if (!isDuplicate) intersections.push(intersect);
      }
    }

    // 按距离起点的距离排序
    return intersections.sort((p1, p2) =>
      calculateDistance(start, p1) - calculateDistance(start, p2)
    );
  };

  // 线段交点计算
  const lineSegmentIntersection = (p1, p2, p3, p4) => {
    const dx1 = p2.lng - p1.lng;
    const dy1 = p2.lat - p1.lat;
    const dx2 = p4.lng - p3.lng;
    const dy2 = p4.lat - p3.lat;
    const denom = dx1 * dy2 - dy1 * dx2;

    if (Math.abs(denom) < EPSILON) return null; // 平行线

    const t = ((p3.lng - p1.lng) * dy2 - (p3.lat - p1.lat) * dx2) / denom;
    const u = ((p3.lng - p1.lng) * dy1 - (p3.lat - p1.lat) * dx1) / denom;

    if (t >= -EPSILON && t <= 1 + EPSILON && u >= -EPSILON && u <= 1 + EPSILON) {
      return {
        lng: p1.lng + t * dx1,
        lat: p1.lat + t * dy1
      };
    }

    return null;
  };

  // 裁剪线段至多边形内
  const clipLineToPolygon = (start, end, polygon) => {
    const intersections = getIntersectionPoints(start, end, polygon);
    const startIn = isPointInPolygon(start, polygon);
    const endIn = isPointInPolygon(end, polygon);

    const points = [];
    if (startIn) points.push({ ...start });
    intersections.forEach(point => points.push({ ...point }));
    if (endIn) points.push({ ...end });

    // 处理奇数个交点的情况
    if (points.length % 2 === 1) {
      if (startIn || endIn) points.pop();
      else points.shift();
    }

    // 清理重复点
    const cleaned = [];
    points.forEach(p => {
      if (!cleaned.some(c => calculateDistance(c, p) <= EPSILON)) {
        cleaned.push(p);
      }
    });

    return cleaned;
  };

  // 计算多边形最小边界矩形(MBR)
  const getMBR = (polygon) => {
    let minLng = Infinity, maxLng = -Infinity;
    let minLat = Infinity, maxLat = -Infinity;

    polygon.forEach(point => {
      minLng = Math.min(minLng, point.lng);
      maxLng = Math.max(maxLng, point.lng);
      minLat = Math.min(minLat, point.lat);
      maxLat = Math.max(maxLat, point.lat);
    });

    return {
      min: { lng: minLng, lat: minLat },
      max: { lng: maxLng, lat: maxLat },
      center: {
        lng: (minLng + maxLng) / 2,
        lat: (minLat + maxLat) / 2
      }
    };
  };

  // 计算多边形直径（最长距离）
  const getPolygonDiameter = (polygon) => {
    let maxDistance = 0;
    for (let i = 0; i < polygon.length; i++) {
      for (let j = i + 1; j < polygon.length; j++) {
        maxDistance = Math.max(maxDistance, calculateDistance(polygon[i], polygon[j]));
      }
    }
    return maxDistance;
  };

  // 主逻辑开始
  const mbr = getMBR(polygon);
  const polygonDiameter = getPolygonDiameter(polygon);
  const lineLength = polygonDiameter * 2; // 确保航线覆盖整个多边形

  // 标准化主角度
  const normalizedAngle = ((mainAngle % 360) + 360) % 360;
  // 旁向间隔方向（垂直于主航线）
  const offsetAngle = (normalizedAngle + 90) % 360;

  // 计算MBR在旁向间隔方向上的宽度（确保覆盖所有区域）
  const mbrDiagonal = calculateDistance(mbr.min, mbr.max);
  const numLines = Math.ceil(mbrDiagonal / sideInterval) + 4; // 多加4条确保覆盖

  // 生成航线
  const routes = [];
  // 从左到右（或从上到下）生成平行航线，确保间距为sideInterval
  const startOffset = -(numLines - 1) / 2 * sideInterval;

  for (let i = 0; i < numLines; i++) {
    // 1. 确保旁向间隔精确：每条航线偏移sideInterval
    const offset = startOffset + i * sideInterval;
    // 计算当前航线的中心点（从MBR中心偏移）
    const lineCenter = destinationPoint(mbr.center, offset, offsetAngle);
    // 生成完整航线（足够长以穿过多边形）
    const line = {
      start: destinationPoint(lineCenter, lineLength / 2, normalizedAngle + 180),
      end: destinationPoint(lineCenter, lineLength / 2, normalizedAngle)
    };

    // 裁剪航线至多边形内部
    const clippedPoints = clipLineToPolygon(line.start, line.end, polygon);
    if (clippedPoints.length < 2) continue; // 跳过无效航线

    const start = clippedPoints[0];
    const end = clippedPoints[clippedPoints.length - 1];

    // 2. 确保航向间隔精确：使用优化的插值函数
    let routePoints = sphericalInterpolate(start, end, courseInterval);

    // 过滤不在多边形内的点
    routePoints = routePoints.filter(p => isPointInPolygon(p, polygon));
    if (routePoints.length < 2) continue;

    // 之字形排列（反转偶数索引航线）
    if (i % 2 === 1) {
      routePoints.reverse();
    }

    // 最终校验并修正点间距
    routePoints = adjustRoutePoints(routePoints, courseInterval);

    routes.push(routePoints);
  }

  // 最终调整函数：确保所有点间距符合要求
  function adjustRoutePoints(points, targetInterval) {
    if (points.length <= 2) return points;

    const adjusted = [points[0]];
    let current = points[0];

    for (let i = 1; i < points.length; i++) {
      const next = points[i];
      const distance = calculateDistance(current, next);

      // 如果距离大于目标间隔，插入中间点
      if (distance > targetInterval + DISTANCE_TOLERANCE) {
        const numSegments = Math.ceil(distance / targetInterval);
        const segmentDistance = distance / numSegments;

        let temp = current;
        for (let j = 1; j < numSegments; j++) {
          temp = moveAlongBearing(temp, next, segmentDistance);
          adjusted.push(temp);
        }
        current = temp;
      }
      // 如果距离在合理范围内，直接添加
      else if (distance > DISTANCE_TOLERANCE) {
        adjusted.push(next);
        current = next;
      }
      // 忽略过近的点
    }

    // 确保终点被包含
    if (!adjusted.some(p => calculateDistance(p, points[points.length - 1]) <= DISTANCE_TOLERANCE)) {
      adjusted.push(points[points.length - 1]);
    }

    return adjusted;
  }

  return routes;
}

// -----------------------------------------------------------------------------------------------------------------------------------------------------------
onMounted(() => {
  form1.value.jixin = '1'
  initMap(() => {




  })
})
// 图层相关变量
const selectedLayer = ref('standard') // 默认选中标准图层
let standardLayer = null // 标准图层实例
let satelliteLayer = null // 卫星图层实例

// 经纬度输入相关
const coordinateInput = ref('') // 经纬度输入框

// 地图实例
let map = null
// 绘制工具
let mouseTool = null
// 编辑工具
let polyEditor = null
// 绘制区域对象
let drawObj = null
// 用于显示边长的文本标记
let lengthMarkers = new Map()
// 当前位置标记
let locationMarker = null

// 状态管理
const isDrawCompleted = ref(false)
const isDrawDisabled = ref(false)
const area = ref(0) // 区域面积(平方公里)

// 开始绘制
const startDraw = () => {
  if (isDrawCompleted.value) {
    ElMessage.error('一次任务只能绘制一个区域，可直接拖动顶点编辑')
    return
  }

  // 确保清除所有可能残留的标记
  clearLengthMarkers()

  // 开启多边形绘制
  mouseTool.polygon({
    strokeColor: "#00B42A", // 绿色轮廓线
    strokeOpacity: 1,
    strokeWeight: 2,
    fillColor: '#87CEFA', // 淡蓝色填充
    fillOpacity: 0.4,
    strokeStyle: "solid",
  })

  // 监听绘制完成事件
  mouseTool.on("draw", handleDrawComplete)
}

// 处理绘制完成
const handleDrawComplete = (event) => {
  console.log("覆盖物对象绘制完成", event)
  drawObj = event.obj
  isDrawCompleted.value = true
  isDrawDisabled.value = true

  // 关闭绘制工具
  mouseTool.close()
  // 移除绘制事件监听
  mouseTool.off("draw", handleDrawComplete)

  // 添加到地图
  drawObj.setMap(map)

  // 计算并显示面积和边长
  calculateAndShowInfo()

  // 初始化编辑工具并开启编辑模式
  initEditor()

  ElMessage.success('区域绘制完成，可直接拖动顶点编辑区域')
}

// 初始化编辑工具
const initEditor = () => {
  AMap.plugin(["AMap.PolyEditor"], function () {
    polyEditor = new AMap.PolyEditor(map, drawObj)

    // 监听编辑过程和完成事件，实时更新信息
    polyEditor.on('addnode', updateInfoOnEdit)
    polyEditor.on('adjust', updateInfoOnEdit)
    polyEditor.on('end', updateInfoOnEdit)

    // 自动开启编辑模式
    polyEditor.open()
  })
}

// 编辑时更新信息
const updateInfoOnEdit = (event) => {
  drawObj = event.target
  calculateAndShowInfo()
}

// 计算并显示面积和边长信息
const calculateAndShowInfo = () => {
  // 清除之前的边长标记
  clearLengthMarkers()

  // 获取多边形路径点
  const path = drawObj.getPath()
  if (!path || path.length < 3) return

  // 计算面积(转换为平方公里)
  const areaSquareMeters = drawObj.getArea()
  area.value = areaSquareMeters / 1000000

  // 计算各边长度并添加标记
  for (let i = 0; i < path.length; i++) {
    const currentPoint = path[i]
    const nextPoint = path[(i + 1) % path.length]

    // 计算两点之间的距离(米)
    const distance = calculateDistanceMap(currentPoint, nextPoint)

    // 计算边的中点(用于放置标记)
    const midPoint = {
      lng: (currentPoint.lng + nextPoint.lng) / 2,
      lat: (currentPoint.lat + nextPoint.lat) / 2
    }

    // 创建文本标记显示边长
    const marker = new AMap.Marker({
      position: [midPoint.lng, midPoint.lat],
      content: `<div class="distance-label">${distance.toFixed(2)}米</div>`,
      anchor: 'bottom-center',
      map: map
    })

    // 使用唯一ID存储标记，便于后续删除
    lengthMarkers.set(`marker-${i}`, marker)
  }
}

// 清除边长标记
const clearLengthMarkers = () => {
  if (lengthMarkers.size > 0) {
    lengthMarkers.forEach((marker, key) => {
      if (marker && marker.remove) {
        try {
          marker.remove()
        } catch (e) {
          console.warn('移除标记时出错:', e)
        }
      }
      lengthMarkers.delete(key)
    })
    lengthMarkers.clear()
  }
}

// 计算两点之间的距离(米)
const calculateDistanceMap = (point1, point2) => {
  return AMap.GeometryUtil.distance(point1, point2)
}

// 删除多边形
const deletePolygon = () => {

  if (!drawObj) return

  flyLinePoint.value = []
  removeFlyLine()
  // 先移除多边形
  if (drawObj.remove) {
    try {
      drawObj.remove()

    } catch (e) {
      console.warn('移除多边形时出错:', e)
    }
  }

  // 关闭并清除编辑工具
  if (polyEditor) {
    polyEditor.close()
    polyEditor.off('change', updateInfoOnEdit)
    polyEditor.off('end', updateInfoOnEdit)
    polyEditor.off('addnode', updateInfoOnEdit)
    polyEditor.off('adjust', updateInfoOnEdit)
    polyEditor = null
  }
  // 强制清除所有长度标记
  clearLengthMarkers()
  // 重置所有状态
  drawObj = null
  isDrawCompleted.value = false
  isDrawDisabled.value = false
  area.value = 0

  ElMessage.success('已删除绘制的区域及所有标记')
}

// 图层切换方法
const switchLayer = () => {
  if (!map) return;

  if (selectedLayer.value === 'satellite') {
    // 切换到卫星图层
    if (standardLayer) standardLayer.hide();
    if (satelliteLayer) {
      satelliteLayer.show();
    } else {
      // 首次创建卫星图层
      AMap.plugin('AMap.TileLayer.Satellite', () => {
        satelliteLayer = new AMap.TileLayer.Satellite();
        map.add(satelliteLayer);
      });
    }
  } else {
    // 切换到标准图层
    if (satelliteLayer) satelliteLayer.hide();
    if (standardLayer) {
      standardLayer.show();
    } else {
      // 首次创建标准图层
      AMap.plugin('AMap.TileLayer', () => {
        standardLayer = new AMap.TileLayer();
        map.add(standardLayer);
      });
    }
  }
}

// 处理经纬度输入框清空事件
const handleCoordinateClear = () => {
  // 清空输入框后，回到当前地理位置
  setMapToCurrentLocation();
  ElMessage.info('已返回当前地理位置');
}

// 根据经纬度搜索并定位
const searchCoordinate = () => {
  if (!coordinateInput.value) {
    ElMessage.warning('请输入经纬度坐标')
    return
  }

  // 解析输入的坐标 (格式: 经度,纬度)
  const [lngStr, latStr] = coordinateInput.value.split(',')
  if (!lngStr || !latStr) {
    ElMessage.error('坐标格式错误，请使用: 经度,纬度')
    return
  }

  const lng = parseFloat(lngStr)
  const lat = parseFloat(latStr)

  if (isNaN(lng) || isNaN(lat)) {
    ElMessage.error('请输入有效的数字坐标')
    return
  }

  // 验证坐标范围
  if (lng < 72 || lng > 138 || lat < 1.8 || lat > 54) {
    ElMessage.warning('坐标不在中国范围内，可能定位不准确')
  }

  // 移动地图并更新标记
  map.setCenter([lng, lat])
  map.setZoom(15)
  addLocationMarker(lng, lat)

  ElMessage.success('已定位到指定坐标')
}

// 在定位点添加标记 - 使用高德默认图标
const addLocationMarker = (lng, lat) => {
  // 如果已有标记，先移除
  if (locationMarker && locationMarker.remove) {
    locationMarker.remove()
  }

  // 创建新标记，使用高德默认样式
  locationMarker = new AMap.Marker({
    position: [lng, lat],
    anchor: 'bottom-center',
    map: map
  })

  // 更新输入框显示当前坐标
  coordinateInput.value = `${lng},${lat}`
}

// 获取当前位置并设置地图中心
const setMapToCurrentLocation = () => {
  if (!navigator.geolocation) {
    ElMessage.warning('您的浏览器不支持地理定位功能，将使用默认位置')
    return false
  }

  navigator.geolocation.getCurrentPosition(
    (position) => {
      console.log('原始WGS-84坐标', position.coords.longitude, position.coords.latitude);
      let longitude = position.coords.longitude; // WGS-84经度
      let latitude = position.coords.latitude;  // WGS-84纬度
      // 判断是否需要转换坐标系（国内坐标需转GCJ-02）
      if (!isLocationOutOfChina(latitude, longitude)) {
        const { slat, slng } = wgs84togcj02(latitude, longitude);
        latitude = slat;
        longitude = slng;
        console.log('转换后GCJ-02坐标', longitude, latitude);
      }
      map.setCenter([longitude, latitude]);
      map.setZoom(15);
      addLocationMarker(longitude, latitude);
      ElMessage.success('已定位到您的当前位置');

    },
    (error) => {
      console.error('定位失败:', error);
      let errorMsg = '获取位置失败，将使用默认位置';

      switch (error.code) {
        case 1:
          errorMsg = '请允许获取地理位置权限，将使用默认位置';
          break;
        case 2:
          errorMsg = '无法获取位置信息，将使用默认位置';
          break;
        case 3:
          errorMsg = '获取位置超时，将使用默认位置';
          break;
      }

      ElMessage.warning(errorMsg);
      const defaultLng = 116.397428; // GCJ-02经度
      const defaultLat = 39.90923;   // GCJ-02纬度
      addLocationMarker(defaultLng, defaultLat);
    }
  );

  return true;
}

// 判断经纬度是否超出中国境内（WGS-84坐标）
function isLocationOutOfChina(lat, lng) {
  // 中国疆域大致范围（WGS-84）
  if (lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271) {
    return true;
  }
  return false;
}

const PI = Math.PI
const a = 6378245.0 //卫星椭球坐标投影到平面地图坐标系的投影因子
const ee = 0.00669342162296594323 //椭球的偏心率

//wgs84 to gcj02   地球坐标系 转 火星坐标系
function wgs84togcj02(lat, lng) {
  let dlat = transformlat(lng - 105.0, lat - 35.0);
  let dlng = transformlng(lng - 105.0, lat - 35.0);
  let radlat = (lat / 180.0) * PI;
  let magic = Math.sin(radlat);
  magic = 1 - ee * magic * magic;
  let sqrtmagic = Math.sqrt(magic);
  dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI);
  dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI);
  let slat = lat + dlat;
  let slng = lng + dlng;

  return { slat, slng };
}

//gcj02 to wgs84  火星坐标系 转 地球坐标系
function gcj02towgs84(lat, lng) {
  const originalLngSign = Math.sign(lng);
  const originalLatSign = Math.sign(lat);
  lat = Math.abs(lat);
  lng = Math.abs(lng);
  let dlat = transformlat(lng - 105.0, lat - 35.0)
  let dlng = transformlng(lng - 105.0, lat - 35.0)
  let radlat = lat / 180.0 * PI
  let magic = Math.sin(radlat)
  magic = 1 - ee * magic * magic
  let sqrtmagic = Math.sqrt(magic)
  dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI)
  dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI)
  let mglat = lat + dlat
  let mglng = lng + dlng
  let lngs = lng * 2 - mglng
  let lats = lat * 2 - mglat
  let slng = originalLngSign * lngs;
  let slat = originalLatSign * lats;

  return { slat, slng };
}

//转化经度
function transformlng(lng, lat) {
  let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
  ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0
  ret += ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) / 3.0
  ret += ((150.0 * Math.sin((lng / 12.0) * PI) + 300.0 * Math.sin((lng / 30.0) * PI)) * 2.0) / 3.0
  return ret
}

//转化纬度
function transformlat(lng, lat) {
  let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng))
  ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0
  ret += ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) / 3.0
  ret += ((160.0 * Math.sin((lat / 12.0) * PI) + 320 * Math.sin((lat * PI) / 30.0)) * 2.0) / 3.0
  return ret
}

// 初始化地图
const initMap = (fun) => {
  AMapLoader.load({
    key: "bcf40c6e056db11948009eec01593cc8", // 你的高德地图key
    version: "2.0",
    plugins: ['AMap.MouseTool', 'AMap.PolyEditor', 'AMap.GeometryUtil', 'AMap.TileLayer', 'AMap.TileLayer.Satellite']
  })
    .then((AMap) => {
      window.AMap = AMap;

      map = new AMap.Map("chat-map", {
        zoom: 15,
        center: [116.397428, 39.90923], // 默认北京（GCJ-02坐标）
        layers: [], // 清空默认图层，自己控制显示内容
        // 禁用POI等地址标记显示
        features: []
      });
      labelsLayer = new AMap.LabelsLayer({});
      map.add(labelsLayer);
      // 初始化图层 - 默认显示标准图层
      AMap.plugin('AMap.TileLayer.Satellite', () => {
        satelliteLayer = new AMap.TileLayer.Satellite();
        map.add(satelliteLayer);
        satelliteLayer.hide();
      });

      // 预加载标准图层
      AMap.plugin('AMap.TileLayer', () => {
        standardLayer = new AMap.TileLayer();
        map.add(standardLayer);
      });

      AMap.plugin("AMap.MouseTool", function () {
        mouseTool = new AMap.MouseTool(map);
      });

      setMapToCurrentLocation()
      fun()
    })
    .catch((e) => {
      console.error('地图加载失败:', e);
    });
}


</script>

<style lang="scss" scoped>
.chat {
  height: 100vh;
  width: 100%;
  display: flex;
  position: relative;

  .chat-map {
    width: 70%;
    height: 100%;
    background: #f5f5f5;
    position: relative;
  }

  // 地图左上角控制区域
  .map-controls {
    position: absolute;
    top: 15px;
    left: 15px;
    z-index: 100;
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 320px;
  }

  .layer-control {
    width: 100%;
  }

  .coordinate-input {
    display: flex;
    gap: 8px;
    width: 100%;
  }

  .chat-set {
    width: 30%;
    padding: 20px;
    box-sizing: border-box;
    border-left: 1px solid #e5e7eb;

    .button-group {
      margin: 10px 0;
      display: flex;
      gap: 10px;
    }

    .area-info {
      margin: 10px 0;
      padding: 10px;
      background-color: #f5f7fa;
      border-radius: 4px;
      color: #303133;
    }
  }
}

// 边长标签样式
:deep(.distance-label) {
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 12px;
  white-space: nowrap;
}

// 覆盖element-ui样式
:deep(.el-select) {
  width: 100%;
}

:deep(.el-input) {
  flex: 1;
}
</style>